home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
CD ROM Paradise Collection 4
/
CD ROM Paradise Collection 4 1995 Nov.iso
/
graphics
/
dxlib50.zip
/
PMIO.INC
< prev
next >
Wrap
Text File
|
1995-02-11
|
52KB
|
1,132 lines
;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
;+ +
;+ PMIO.INC Version 2.0 Source Code +
;+ +
;+ Copyright 1993-1995, by TechniLib (TM) Company +
;+ All Rights Reserved +
;+ +
;+ SALE OR USE OF SOFTWARE DEVELOPED WITH +
;+ UNREGISTERED COPIES OF THIS CODE +
;+ INFRINGES COPYRIGHT +
;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
; Protected-Mode Input/Output Procedures.
; Version 2.0
;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
;
; All PMIO procedures assume that the code is resident in a 32-bit segment.
;Other assumptions are also made, but these may be changed with conditional
;assembly directives explained below.
; A full explanation of each IO procedure is provided above the procedure.
;The following is a brief summary:
;
;Screen Procedures
;-----------------
;
; The screen procedures always print at the recorded BIOS cursor position and
;update the BIOS position after printing; however, they do not adjust the video
;hardware to actually relocate the cursor on the screen. Call UPDATECSR for
;this purpose.
; PMIO never uses DOS. The screen procedures avoid all calls to BIOS.
;Therefore, they should function properly within interrupt handlers.
; The screen address is assumed to be B8000H, which will be the case for
;color monitors. For monochrome monitors, set SCRNBASEADR below to B0000H.
;
;Procedure Description
;PCH Print ASCII character in AL
;CRLF Issue carriage return and line feed
;SCRLUP Scoll screen up
;CLS Clear screen
;SPC Print AL spaces
;PSTR Print zero terminated ASCII string at DS:EBX
;PESSTR Print zero terminated ASCII string at ES:EBX
;PCSSTR Print zero terminated ASCII string at CS:EBX
;PHB Print BYTE in AL as hexadecimal
;PHW Print WORD in AX as hexadecimal
;PHD Print DWORD in EAX as hexadecimal
;PUB Print unsigned BYTE in AL as decimal
;PUW Print unsigned WORD in AX as decimal
;PUD Print unsigned DWORD in EAX as decimal
;PSB Print signed BYTE in AL as decimal
;PSW Print signed WORD in AX as decimal
;PSD Print signed DWORD in EAX as decimal
;PFST Print ST of FPU using format in AX. AH = characters to left of
; decimal. AL = characters to right of decimal.
;
;Keyboard Procedures
;-------------------
;
;Procedure Description
;GETCH Get character from keyboard in AX. AL = either ASCII code or
; scan code. If sign bit of AH is set, then scan code. Other bits
; in AH define the state of shift and toggle keys (see procedure
; for detail). Character is not echoed.
;EDITSTR Display and edit string at DS:EBX. Call with EAX = maximum
; length of final string. See procedure for details.
;SETCSRPOS Set cursor position. Call with (AH,AL) = (row,column). Rows
; range from zero (top) to 24 (bottom). Columns range from zero
; (left) to 79 (right).
;GETCSRPOS Get cursor position in AX. (AH,AL) = (row,column).
;UPDATECSR Physically relocate cursor on screen to current BIOS coordinates.
;SETCSRTYPE Set cursor type. Call with AL = 0 for underline, or 1 for block.
; Call with sign bit of AL set to disable the cursor.
;SETCSR Set cursor position and type. Call with position in DX and type
; in CX. CH = start scan line, and CL = end scan line. Scan lines
; range from 0 (top) to 7 (bottom).
;GETCSR Get cursor position/type in DX/CX (CH/CL = start/end scan line).
;
;Speaker Procedures
;------------------
;
;Procedure Description
;BEEP Produce beep through speaker.
;
;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
; PMIO.INC Switches
;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
;
; There are two switches affecting the way PMIO.INC assembles. Both switches
;default to FALSE. The switches should be defined before the inclusion of
;PMIO.INC
;
;1) TASMMODE:
;
; TASM users should set TASMMODE to TRUE.
;
;2) ASSUMEFLAT:
;
; If it may always be assumed that DS contains a flat-model selector, then set
;ASSUMEFLAT to TRUE. This will increase speed.
;
;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
; Important Changes from Earlier Version of PMIO
;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
;
; Many changes have been made to PMIO.INC. Some of these may necessitate
;changes to code using earlier versions. Important changes are:
;
;1) PSTR prints the string at DS:EBX rather than ES:EBX. A new procedure
; called PESSTR prints from ES:EBX.
;2) PCH, PSTR, PCSSTR, and PESSTR now translate character 13 to a carriage
; return-linefeed combination. 13,10 is translated the same (10 is ignored).
; Character 7 is translated to a beep at the speaker. Earlier versions of
; PMIO.INC did not translate control codes.
;3) The procedure PFST has been renamed to PFST.
;4) Earlier versions of PMIO.INC assumed that DS was loaded with a flat
; selector (base = 0). This version assumes nothing about segment
; registers (DS is always reloaded). This produces no incompatibility.
; However, to emulate older versions, set ASSUMEFLAT to TRUE.
;5) The present version contains a new procedure called EDITSTR which is a
; powerful string edit/input function. Other new procedures have been added
; to handle BYTE data. These are: PHB, PUB, and PSB.
;
;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
TRUE EQU 1
FALSE EQU 0
IFDEF TASMMODE
DOTASM = TASMMODE
ELSE
DOTASM = FALSE
ENDIF
IFDEF ASSUMEFLAT
DOFLAT = ASSUMEFLAT
ELSE
DOFLAT = FALSE
ENDIF
IF DOTASM
MASM51
QUIRKS
LARGESTACK
PUSHW MACRO IMMEDIATE16:REST ;PUSH immediate 16-bit data
IF (@WordSize EQ 4)
DB 66H
ENDIF
DB 68H
DW IMMEDIATE16
ENDM
PUSHD MACRO IMMEDIATE32:REST ;PUSH immediate 32-bit data
IF (@WordSize EQ 2)
DB 66H
ENDIF
DB 68H
DD IMMEDIATE32
ENDM
ENDIF ;IF DOTASM
IF DOFLAT ;DS always contains FLATDSEL
SETDS MACRO ;Does nothing
ENDM
RESETDS MACRO ;Does nothing
ENDM
ELSE ;DS must be loaded with FLATDSEL
SETDS MACRO
PUSH DS
MOV DS,CS:CSDSEGSEL ;Load DSEG selector
ASSUME DS:DSEG
MOV DS,FLATDSEL
ASSUME DS:TSEG
ENDM
RESETDS MACRO
POP DS
ENDM
ENDIF
;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
;Local Data and Constants
;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
ALIGN 4
SCRNBASEADR DD 000B8000H ;Screen address
CURPOSADR DD 00000450H ;BIOS address containing cursor position
SCRNATR DB 07H ;Attribute for CLS (white over black)
;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
;Screen Routines
;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
;Print ASCII code in AL at cursor.
PCH PROC NEAR
CMP AL,0DH ;Effectively append linefeed to carriage return
JE CRLF
CMP AL,0AH ;Do nothing with linefeeds
JE DORET
CMP AL,7 ;Ring bell
JE BEEP
PUSH EBX
PUSH EDX
SETDS
MOV EDX,CS:CURPOSADR ;Cursor (row,col) in (DH,DL)
PUSH EDX ;PUSH cursor address
MOV EDX,[EDX]
PUSH EDX ;PUSH cursor position
XOR EBX,EBX
MOV BL,DH
SHL EBX,5 ;Multiply row by 160
LEA EBX,[EBX+4*EBX] ;160 = 32 + 4 * 32
AND EDX,0FFH ;Clear all but column
LEA EBX,[EBX+2*EDX]
ADD EBX,CS:SCRNBASEADR
POP EDX ;POP cursor position
MOV [EBX],AL
INC DL ;Increment column
CMP DL,79
JBE RCDCURSOR
XOR DL,DL ;Move to zero column of next row
INC DH ;Move to next row
RCDCURSOR: POP EBX ;POP cursor address
MOV [EBX],DX ;Assume row is valid
CMP DH,24
JA DOSCROLL
EXIT:
RESETDS
POP EDX
POP EBX
DORET: RET
DOSCROLL: PUSHD OFFSET EXIT
JMP SCRLUP
PCH ENDP
;Clear from cursor to end of line and issue CRLF. Scroll up if necessary.
CRLF PROC NEAR
PUSH EAX
PUSH EBX
PUSH ECX
SETDS
MOV EAX,CS:CURPOSADR
PUSH EAX ;PUSH cursor address
MOV EAX,[EAX] ;Get cursor position
PUSH EAX ;PUSH cursor position
XOR EBX,EBX
MOV BL,AH
SHL EBX,5 ;Multiply row by 160
LEA EBX,[EBX+4*EBX] ;160 = 32 + 4 * 32
AND EAX,0FFH ;Clear all but column
MOV CL,80
SUB CL,AL ;Get number of bytes to clear in CL
LEA EBX,[EBX+2*EAX]
ADD EBX,CS:SCRNBASEADR
MOV AL,32
CLREOL: MOV [EBX],AL ;Clear to end of line
ADD EBX,2
DEC CL
JNZ CLREOL
POP EAX ;POP cursor position
POP EBX ;POP cursor address
INC AH ;Increment row
CMP AH,24
JA DOSCROLL
XOR AL,AL ;Set column to zero
MOV [EBX],AX
EXIT:
RESETDS
POP ECX
POP EBX
POP EAX
RET
DOSCROLL: PUSHD OFFSET EXIT
JMP SCRLUP
CRLF ENDP
;Scroll entire screen up one line and leave cursor at start of line 24.
SCRLUP PROC NEAR
PUSH EAX
PUSH EBX
PUSH ECX
SETDS
MOV EBX,CS:SCRNBASEADR
MOV ECX,960 ;960 = (80*24*2)/4 (DWORDS to scroll)
SCROLLLOOP: MOV EAX,[EBX+160]
MOV [EBX],EAX
ADD EBX,4
DEC ECX
JNZ SCROLLLOOP
MOV CL,80
MOV AL,32
CLR24: MOV [EBX],AL ;Clear line 24
ADD EBX,2
DEC CL
JNZ CLR24
EXIT: MOV EAX,CS:CURPOSADR
MOV WORD PTR [EAX],1800H ;Set cursor to bottom line in zero column
RESETDS
POP ECX
POP EBX
POP EAX
RET
SCRLUP ENDP
;Clear screen and leave cursor at (0,0) position.
CLS PROC NEAR
PUSH EAX
PUSH EBX
PUSH ESI
SETDS
MOV EBX,CS:SCRNBASEADR
MOV ESI,999
MOV AL,20H
MOV AH,CS:SCRNATR
PUSH AX
PUSH AX
POP EAX
DOCLS: MOV [EBX+4*ESI],EAX
DEC ESI
JNS DOCLS
MOV EAX,CS:CURPOSADR
MOV WORD PTR [EAX],0H
RESETDS
POP ESI
POP EBX
POP EAX
RET
CLS ENDP
;Print AL spaces at cursor.
SPC PROC NEAR
OR AL,AL
JZ EXIT
PUSH EAX
MOV AH,AL
MOV AL,32
PRINTSPC: CALL PCH
DEC AH
JNZ PRINTSPC
POP EAX
EXIT: RET
SPC ENDP
;Print ASCIIZ string at address in DS:EBX.
PSTR PROC NEAR
PUSH EAX
PUSH EBX
CHARLOOP: MOV AL,[EBX]
OR AL,AL ;See if at end of string
JZ EXIT
CALL PCH
INC EBX
JMP CHARLOOP
EXIT: POP EBX
POP EAX
RET
PSTR ENDP
;Print ASCIIZ string at address ES:EBX.
PESSTR PROC NEAR
PUSH DS
PUSH ES
POP DS
CALL PSTR
POP DS
RET
PESSTR ENDP
;Print ASCIIZ string at address CS:EBX.
PCSSTR PROC NEAR
PUSH EAX
PUSH EBX
CHARLOOP: MOV AL,CS:[EBX] ;See if at end of string
OR AL,AL
JZ EXIT
CALL PCH
INC EBX
JMP CHARLOOP
EXIT: POP EBX
POP EAX
RET
PCSSTR ENDP
;Print hexadecimal BYTE in AL.
PHB PROC NEAR
PUSH EAX
MOV AH,AL
SHR AL,4
AND AH,0FH
ADD AX,3030H
CMP AL,57
JBE FIXAH
ADD AL,7
FIXAH: CMP AH,57
JBE PRINTCHARS
ADD AH,7
PRINTCHARS: CALL PCH
MOV AL,AH
CALL PCH
POP EAX
RET
PHB ENDP
;Print hexadecimal WORD in AX.
PHW PROC NEAR
PUSH EAX
PUSH ECX
PUSH EDX
MOV EDX,EAX
MOV CL,4 ;Print four nibbles
CALCNIBS: MOV AL,DL
AND AL,0FH
ADD AL,48
CMP AL,57
JBE PUSHDIGIT
ADD AL,7
PUSHDIGIT: PUSH EAX
SHR EDX,4
DEC CL
JNZ CALCNIBS
MOV CL,4
PRNTNIBS: POP EAX
CALL PCH
DEC CL
JNZ PRNTNIBS
POP EDX
POP ECX
POP EAX
RET
PHW ENDP
;Print hexadecimal DWORD in EAX.
PHD PROC NEAR
PUSH EAX
PUSH ECX
PUSH EDX
MOV EDX,EAX
MOV CL,8 ;Print eight nibbles
CALCNIBS: MOV AL,DL
AND AL,0FH
ADD AL,48
CMP AL,57
JBE PUSHDIGIT
ADD AL,7
PUSHDIGIT: PUSH EAX
SHR EDX,4
DEC CL
JNZ CALCNIBS
MOV CL,8
PRNTNIBS: POP EAX
CALL PCH
DEC CL
JNZ PRNTNIBS
POP EDX
POP ECX
POP EAX
RET
PHD ENDP
;Print unsigned BYTE in AL as decimal.
PUB PROC NEAR
PUSH EAX
AND EAX,0FFH
JMP PUINT
PUB ENDP
;Print unsigned WORD in AX as decimal.
PUW PROC NEAR
PUSH EAX
AND EAX,0FFFFH
JMP PUINT
PUW ENDP
;Print unsigned DWORD in EAX as decimal.
PUD PROC NEAR
PUSH EAX
PUINT LABEL NEAR
PUSH EBX
PUSH ECX
PUSH EDX
XOR ECX,ECX
MOV EBX,10
CALCDIGS: XOR EDX,EDX
DIV EBX
PUSH EDX
INC ECX
OR EAX,EAX
JNZ CALCDIGS
PRNTDIGS: POP EAX
ADD AL,48
CALL PCH
DEC ECX
JNZ PRNTDIGS
POP EDX
POP ECX
POP EBX
POP EAX
RET
PUD ENDP
;Print signed BYTE in AL as decimal.
PSB PROC NEAR
PUSH EAX
MOVSX EAX,AL
JMP PSINT
PSB ENDP
;Print signed WORD in AX as decimal.
PSW PROC NEAR
PUSH EAX
MOVSX EAX,AX
JMP PSINT
PSW ENDP
;Print signed DWORD in EAX as decimal.
PSD PROC NEAR
PUSH EAX
PSINT LABEL NEAR
OR EAX,EAX
JNS PABS
PUSH EAX
MOV AL,"-"
CALL PCH
POP EAX
NEG EAX ;Calculate absolute value
PABS: CALL PUD ;Print absolute value
POP EAX
RET
PSD ENDP
;Print ST of FPU using format code in AX. Call with lowest seven bits of AH =
;number of high-order digits plus the sign (if negative), and lowest five bits
;of AL = number of low-order digits. Fractions are printed with leading zeros
;if the sign bit of AH is clear. Will print numbers absolutely smaller than
;10 ^ 18 and will print up to 18 decimal places. Will fill entire print field
;with "*" if high-order digit field is too small. Will fill entire print field
;with ">" if number is absolutely greater than or equal to 10 ^ 18. It is
;assumed that ST contains a valid number. AL must not be greater than 18.
PFST PROC NEAR
LOCAL FLDWIDTH:DWORD ;The width of the print field
LOCAL NOHIDIGITS:DWORD ;Number of high-order digits
LOCAL NOLODIGITS:DWORD ;Number of low-order digits
LOCAL OLDCWORD:DWORD ;Old FPU control word
LOCAL NEWCWORD:DWORD ;Local FPU control word
LOCAL HIDIGITS[10]:BYTE ;Storage for high-order digit string
LOCAL LODIGITS[10]:BYTE ;Storage for low-order digit string
PUSH EAX
PUSH EBX
PUSH ECX
PUSH EDX
PUSH ESI
PUSH EDI
XOR EBX,EBX ;Assume no leading zeros on fractions
XOR ECX,ECX
CHKLEADZERO: OR AH,AH ;Test assumption
JS SETFLDSIZES ;Leading zeros are suppressed
INC EBX ;Will print leading zeros
SETFLDSIZES: AND AH,7FH ;Mask leading zero flag
MOV CL,AH ;Set ECX = number of high order digits + sign
MOV NOHIDIGITS,ECX
MOV CL,AL ;Set ECX = number of decimal places
MOV NOLODIGITS,ECX
ADD AL,AH ;Compute field width in EAX
AND EAX,0FFH
OR ECX,ECX ;See if any low order digits
JZ SETFLDWIDTH
INC EAX ;Account for decimal point
SETFLDWIDTH: MOV FLDWIDTH,EAX
FTST
XOR ECX,ECX ;Set ECX to sign flag
FSTSW AX
SAHF
JAE SETCWORD
INC ECX ;Number is negative
SETCWORD: FSTCW WORD PTR OLDCWORD[0] ;Save original control word
MOV EAX,OLDCWORD
OR AH,0FH ;Set PC to 64 bits and RC to truncate
MOV NEWCWORD,EAX
FLDCW WORD PTR NEWCWORD[0]
FLD ST ;See if number of high order digits is greater than 18
FABS
FCOM CS:FPPOWERTEN[8*18]
FSTSW AX
SAHF
JAE OVERFLOW
FLD ST
FRNDINT
MOV EAX,NEWCWORD
MOV ESI,NOLODIGITS
AND AH,03H ;Set RC for round to nearest
XOR EDX,EDX
MOV NEWCWORD,EAX
XOR EDI,EDI
FLDCW WORD PTR NEWCWORD[0]
FSUB ST(1),ST ;Complete low order digits
FXCH
FMUL CS:FPPOWERTEN[8*ESI] ;Convert to integer
FRNDINT
FCOM CS:FPPOWERTEN[8*ESI] ;See if low order digits rounded to one
MOV ESI,8
FSTSW AX
SAHF
JB WRITEDIGITS
FSTP ST
FLD1
FADD
FLDZ ;Set low order digits to zero
WRITEDIGITS: FBSTP TBYTE PTR LODIGITS[0]
FBSTP TBYTE PTR HIDIGITS[0]
GETHIDIGIT: OR DL,HIDIGITS[ESI] ;Find first nonzero digit
JNZ CALCHIORDER
DEC ESI
JNS GETHIDIGIT
MOV ESI,EBX ;No high order digits, so add leading zero if any
JMP ADDSIGN
CALCHIORDER: MOV EDI,ESI ;Save offset in EDI
INC ESI ;Convert ESI to number of high order digits
ADD ESI,ESI
TEST DL,0F0H ;See if highest digit is in odd position
JNZ ADDSIGN
DEC ESI
ADDSIGN: ADD ESI,ECX ;Account for possible "-"
MOV EAX,NOHIDIGITS
SUB EAX,ESI ;See if field for high-order digits and sign is large enough
JB SMALLFLD
CALL SPC ;Print leading spaces
PRNTSIGN: OR ECX,ECX
JZ PRNTHIDIGITS
MOV AL,"-"
CALL PCH
DEC ESI
DEC ECX ;Set ECX = 0
PRNTHIDIGITS: OR ESI,ESI ;See if any high order digits are to be printed
JZ PRNTDEC
AND ESI,01H
JNZ ODDHIDIGIT
HIDIGITLOOP: MOV DL,HIDIGITS[EDI]
MOV AL,DL
SHR AL,4
ADD AL,48
CALL PCH
ODDHIDIGIT: MOV AL,DL
AND AL,0FH
ADD AL,48
CALL PCH
DEC EDI
JNS HIDIGITLOOP
PRNTDEC: OR ECX,NOLODIGITS ;See if any low order digits are to be printed
JZ EXIT
MOV EDI,ECX ;Find byte number for first digit
DEC EDI
SHR EDI,1
MOV AL,"."
CALL PCH
MOV DL,LODIGITS[EDI]
AND CL,01H
JNZ ODDLODIGIT
LODIGITLOOP: MOV DL,LODIGITS[EDI]
MOV AL,DL
SHR AL,4
ADD AL,48
CALL PCH
ODDLODIGIT: MOV AL,DL
AND AL,0FH
ADD AL,48
CALL PCH
DEC EDI
JNS LODIGITLOOP
EXIT: FLDCW WORD PTR OLDCWORD[0] ;Restore calling control word
POP EDI
POP ESI
POP EDX
POP ECX
POP EBX
POP EAX
RET
FILLFLD: MOV ECX,FLDWIDTH
RCDCHAR: CALL PCH ;Print one character even if field width is zero
DEC ECX
JNZ RCDCHAR
JMP EXIT
SMALLFLD: MOV AL,"*"
JMP FILLFLD
OVERFLOW: FSTP ST ;Pop absolute value of number
MOV AL,">"
JMP FILLFLD
ALIGN 8
FPPOWERTEN LABEL QWORD
DQ 1.0E0
DQ 1.0E1
DQ 1.0E2
DQ 1.0E3
DQ 1.0E4
DQ 1.0E5
DQ 1.0E6
DQ 1.0E7
DQ 1.0E8
DQ 1.0E9
DQ 1.0E10
DQ 1.0E11
DQ 1.0E12
DQ 1.0E13
DQ 1.0E14
DQ 1.0E15
DQ 1.0E16
DQ 1.0E17
DQ 1.0E18
PFST ENDP
;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
;Keyboard Routines
;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
;Get chracter from keyboard without echo. Return ASCII code or scan code in AL.
;The sign bit of AH is set if a scan code. The state of the shift keys is also
;in AH. Bits of AH are defined: 0 = shift, 1 = ctrl, 2 = alt, 3 = scroll lock,
;4 = num lock, 5 = caps lock, 6 = insert. The high word of EAX is cleared.
;Interrupts must be enabled. If CTRL C is entered, then INT 23H is executed.
GETCH PROC NEAR
PUSH EDX
MOV AH,10H ;Remove key from type-ahead buffer. Will wait if no key present
INT 16H ;Scan code in AH, ASCII code in AL
MOV EDX,EAX
MOV AH,12H ;Get state of flags
INT 16H
TEST AL,01H ;Combine right and left shift keys
JZ FIXFLAGS
OR AL,02H
FIXFLAGS: SHR AL,1
AND EAX,07FH
MOV AH,AL
MOV AL,DL ;Put ASCII scan code in AL
CMP AL,0E0H ;See if the character is for non-ASCII enhanced keyboard key
JE DOSCAN
OR AL,AL ;See if the character is for a non-ASCII key
JZ DOSCAN
CMP AL,03H ;See if character is CTRL C
JNE EXIT
INT 23H ;Do CTRL C interrupt
DOSCAN: MOV AL,DH ;Put scan code in AL
OR AH,80H ;Set high bit to denote scan code
EXIT: POP EDX
RET
GETCH ENDP
;Display ASCIIZ string at DS:EBX at the cursor and then edit. Call with
;EAX set to maximum length for final string (excluding terminating zero).
;Editor processes BACKSPACE, DELETE, LEFT and RIGHT ARROW, INSERT, HOME, END,
;ENTER, and all noncontrol ASCII codes. All other keys will cause editor to
;exit with no modification to the string. ENTER causes editor to exit with
;modifications being returned. Leading and trailing spaces are stripped from
;the returned string. The last typed character is returned in AX. See GETCH
;for format of AX.
EDITSTR PROC NEAR
LOCAL STARTADR:DWORD ;Screen address of first character in edit field
LOCAL ENDADR:DWORD ;Screen address of last character in edit field
PUSH ECX
PUSH EDX
PUSH ESI
IFE DOFLAT
PUSH ES
PUSH DS
ENDIF
PUSH EBX
PUSH EAX ;Save maximum width of string
CALL GETCSRADR ;Compute starting screen address for string
MOV STARTADR,EDX
XCHG [ESP],EAX ;Put starting cursor coordinates on stack and get field width in EAX
CALL SPC ;Clear display field
CALL GETCSRADR ;Compute ending screen address
SUB EDX,2
MOV ENDADR,EDX
POP EDX ;Pop original cursor coordinates
MOV CX,0607H ;Specify underline cursor
CALL SETCSR ;Reset cursor to beginning of field
CALL PSTR ;Display string
CALL UPDATECSR
CALL GETCSRADR ;Get current cursor screen address
IFE DOFLAT ;Set DS:EBX to address of string on screen
MOV DS,CS:CSDSEGSEL
ASSUME DS:DSEG
MOV DS,FLATDSEL
ASSUME DS:TSEG
ENDIF
MOV EBX,EDX
XOR ESI,ESI ;ESI = cursor mode flag (0 = insert, 1 = overtype)
JMP GETKEY
FIXCURSOR: MOV EAX,EBX ;Compute cursor coordinates from screen address in EBX
SUB EAX,CS:SCRNBASEADR
SHR EAX,1
MOV DL,80
DIV DL
XCHG AH,AL
MOV EDX,EAX ;Put coordinates in DX
MOV CX,0607H ;Assume underline cursor
OR ESI,ESI ;Test assumption
JZ SETCURSOR
XOR CH,CH ;Specify block cursor
SETCURSOR: CALL SETCSR ;Set cursor type and position
GETKEY: CALL GETCH ;Get character
OR AH,AH ;See if special key
JS DOSPECIAL
CMP AL,8 ;See if BACKSPACE
JE DOBS
CMP AL,13 ;See if ENTER
JE STORESTR ;Store string and exit
CMP AL,32 ;See if other control key
JB EXIT ;Exit without modifying string
MOV ECX,ENDADR ;See if cursor beyond field
CMP EBX,ECX
JA DOBEEP
OR ESI,ESI ;Check cursor mode
JNZ WRITECHAR ;JMP if in overtype mode
CMP BYTE PTR [ECX]," " ;See if field is full
JE ENTERLOOP ;Perform insert
JMP DOBEEP
SHIFTRIGHT: MOV DL,[ECX-2] ;Shift characters right beginning with current character
MOV [ECX],DL
SUB ECX,2
ENTERLOOP: CMP ECX,EBX
JA SHIFTRIGHT
WRITECHAR: MOV [EBX],AL ;Write character
ADD EBX,2 ;Advance cursor
JMP FIXCURSOR
DOBS: CMP EBX,STARTADR ;See if at first character
JE GETKEY
SUB EBX,2
JMP DODELETE
DOSPECIAL: TEST AH,07H ;Ensure that none of SHIFT, CTRL, or ALT were pressed
JNZ EXIT ;Exit without modifying string
CMP AL,4BH ;See if LEFT ARROW
JNE CHKRIGHT
CMP EBX,STARTADR ;See if already at left of field
JE GETKEY
SUB EBX,2 ;Decrement cursor
JMP FIXCURSOR
CHKRIGHT: CMP AL,4DH ;See if RIGHT ARROW
JNE CHKDEL
CMP EBX,ENDADR ;See if cursor already past right of field
JA GETKEY
ADD EBX,2
JMP FIXCURSOR
CHKDEL: CMP AL,53H ;See if DELETE
JNE CHKINS
DODELETE: MOV ECX,EBX
CMP EBX,ENDADR ;See if cursor beyond print field
JA GETKEY
JE PUTSPACE ;Are at terminal character
SHIFTLEFT: MOV AL,[ECX+2] ;Shift characters left beginning with next character
MOV [ECX],AL
ADD ECX,2
CMP ECX,ENDADR
JB SHIFTLEFT
PUTSPACE: MOV BYTE PTR [ECX]," "
JMP FIXCURSOR
CHKINS: CMP AL,52H ;See if INSERT
JNE CHKHOME
XOR ESI,01H ;Toggle cursor mode
JMP FIXCURSOR
CHKHOME: CMP AL,47H ;See if HOME
JNE CHKEND
MOV EBX,STARTADR
JMP FIXCURSOR
CHKEND: CMP AL,4FH ;See if END
JNE EXIT
MOV EBX,ENDADR
FINDENDLOOP: CMP BYTE PTR [EBX]," "
JNE GOTEND
SUB EBX,2
CMP EBX,STARTADR
JAE FINDENDLOOP
GOTEND: ADD EBX,2
JMP FIXCURSOR
STORESTR:
IFE DOFLAT
PUSH DS ;Set ES to flat selector
POP ES
LDS EBX,[ESP] ;Reset DS:EBX to screen address
ELSE
MOV EBX,[ESP]
ENDIF
MOV ECX,STARTADR ;ES:ECX = address of string on screen
MOV ESI,EBX ;ESI will be pointer to last nonspace character in string
TRIMLOOP:
IFE DOFLAT
MOV DL,ES:[ECX] ;Move past leading spaces
ELSE
MOV DL,[ECX]
ENDIF
ADD ECX,2
CMP DL," "
JNE MOVCHAR
CMP ECX,ENDADR
JBE TRIMLOOP
JMP PUTZERO ;The string is all spaces soo return null string
MOVSTRLOOP:
IFE DOFLAT
MOV DL,ES:[ECX]
ELSE
MOV DL,[ECX]
ENDIF
ADD ECX,2
CMP DL," "
JE MOVCHAR
MOV ESI,EBX
MOVCHAR: MOV [EBX],DL
INC EBX
CMP ECX,ENDADR
JBE MOVSTRLOOP
MOV EBX,ESI ;Set EBX to position after last nonspace character
INC EBX
PUTZERO: MOV BYTE PTR [EBX],0H
EXIT: POP EBX
IFE DOFLAT
POP DS
POP ES
ENDIF
POP ESI
POP EDX
POP ECX
RET
DOBEEP: PUSHD OFFSET GETKEY
JMP BEEP
GETCSRADR: CALL GETCSRPOS ;Get cursor coordinates
PUSH EAX ;Save coordinates
XOR EDX,EDX ;Multiply row by 160
MOV DL,AH
SHL EDX,5 ;Multiply by 32
LEA EDX,[EDX+4*EDX] ;Multiply by 5
AND EAX,0FFH ;Mask all but column
LEA EDX,[EDX+2*EAX]
ADD EDX,CS:SCRNBASEADR
POP EAX ;Restore coordinates
RETN
EDITSTR ENDP
;Set cursor position at (row,col) = (AH,AL).
SETCSRPOS PROC NEAR
PUSH EAX
PUSH EBX
PUSH EDX
CMP AH,24 ;Do not allow row greater than 24
JBE CHKCOL
MOV AH,24
CHKCOL: CMP AL,79 ;Do not allow column greater than 79
JBE SETCURSOR
MOV AL,79
SETCURSOR: MOV EDX,EAX ;Place coordinates in DX
XOR EBX,EBX ;Use screen zero
MOV AH,02H ;Function to set cursor position
INT 10H
POP EDX
POP EBX
POP EAX
RET
SETCSRPOS ENDP
;Get cursor position in (AH,AL) = (row,col)
GETCSRPOS PROC NEAR
PUSH EBX
PUSH ECX
PUSH EDX
MOV AH,03H ;Function to get cursor position
XOR EBX,EBX ;Get position for screen zero
INT 10H ;Cursor position returned in DX, and type returned in CX
MOV EAX,EDX
POP EDX
POP ECX
POP EBX
RET
GETCSRPOS ENDP
;Physically relocate the cursor on the screen to the current BIOS coordinates.
UPDATECSR PROC NEAR
PUSH EAX
CALL GETCSRPOS
CALL SETCSRPOS
POP EAX
RET
UPDATECSR ENDP
;Set cursor type. Call with AL = 1 for block, AL = 0 for underline, and sign
;bit of AL set to disable.
SETCSRTYPE PROC NEAR
PUSH EAX
PUSH ECX
MOV AH,01H
MOV CX,0607H ;Assume underline cursor
OR AL,AL
JZ SETCURLINES
JS DISABLECSR
XOR CH,CH ;Set to block cursor
JMP SETCURLINES
DISABLECSR: MOV CH,20H ;Disable cursor
SETCURLINES: INT 10H
POP ECX
POP EAX
RET
SETCSRTYPE ENDP
;Get cursor position and type. Position in DX and type in CX.
GETCSR PROC NEAR
PUSH EAX
PUSH EBX
MOV AH,03H ;Function to get cursor position
XOR EBX,EBX ;BH = page
INT 10H ;(start,end) scan line for cursor in (CH,CL)
POP EBX ;(row/column) for cursor in (DH,DL)
POP EAX
RET
GETCSR ENDP
;Set cursor position and type. Call with (DH,DL) = (row,col) for cursor and
;(CH,CL) = (start,end) scan line for cursor.
SETCSR PROC NEAR
PUSH EAX
PUSH EBX
MOV AH,02H ;Set cursor position
XOR EBX,EBX ;Use page zero
INT 10H
DEC AH ;Set cursor type
INT 10H
POP EBX
POP EAX
RET
SETCSR ENDP
;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
;Speaker Routines
;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
;Produce beep through speaker.
BEEP PROC NEAR
PUSH EAX
PUSH ECX
PUSH EDX
IN AL,61H
MOV DX,6818 ;175 cycles/second
CALL SOUND
MOV CX,3 ;Delay for .25 seconds
MOV DX,0D000H
MOV AH,86H
INT 15H
OUT 61H,AL
POP EDX
POP ECX
POP EAX
RET
BEEP ENDP
;Activate speaker. Call with frequency divisor in DX. Divisor = 1,193,180
;divided by cycles per second.
SOUND PROC NEAR
PUSH EAX
MOV AL,10110110B ;Channel 2, LSB/MSB, mode 3, binary
OUT 43H,AL ;Program the timer
MOV EAX,EDX
OUT 42H,AL
MOV AL,AH
OUT 42H,AL
IN AL,61H
OR AL,03H ;Enable speaker and use channel 2 for input
OUT 61H,AL
POP EAX
RET
SOUND ENDP
IFE DOTASM
EXTERNDEF PASCAL PCH:NEAR
EXTERNDEF PASCAL CRLF:NEAR
EXTERNDEF PASCAL SCRLUP:NEAR
EXTERNDEF PASCAL CLS:NEAR
EXTERNDEF PASCAL SPC:NEAR
EXTERNDEF PASCAL PSTR:NEAR
EXTERNDEF PASCAL PESSTR:NEAR
EXTERNDEF PASCAL PCSSTR:NEAR
EXTERNDEF PASCAL PHB:NEAR
EXTERNDEF PASCAL PHW:NEAR
EXTERNDEF PASCAL PHD:NEAR
EXTERNDEF PASCAL PUB:NEAR
EXTERNDEF PASCAL PUW:NEAR
EXTERNDEF PASCAL PUD:NEAR
EXTERNDEF PASCAL PSB:NEAR
EXTERNDEF PASCAL PSW:NEAR
EXTERNDEF PASCAL PSD:NEAR
EXTERNDEF PASCAL PFST:NEAR
EXTERNDEF PASCAL GETCH:NEAR
EXTERNDEF PASCAL EDITSTR:NEAR
EXTERNDEF PASCAL SETCSRPOS:NEAR
EXTERNDEF PASCAL GETCSRPOS:NEAR
EXTERNDEF PASCAL UPDATECSR:NEAR
EXTERNDEF PASCAL SETCSRTYPE:NEAR
EXTERNDEF PASCAL SETCSR:NEAR
EXTERNDEF PASCAL GETCSR:NEAR
EXTERNDEF PASCAL BEEP:NEAR
ELSE
GLOBAL PASCAL PCH:NEAR
GLOBAL PASCAL CRLF:NEAR
GLOBAL PASCAL SCRLUP:NEAR
GLOBAL PASCAL CLS:NEAR
GLOBAL PASCAL SPC:NEAR
GLOBAL PASCAL PSTR:NEAR
GLOBAL PASCAL PESSTR:NEAR
GLOBAL PASCAL PCSSTR:NEAR
GLOBAL PASCAL PHB:NEAR
GLOBAL PASCAL PHW:NEAR
GLOBAL PASCAL PHD:NEAR
GLOBAL PASCAL PUB:NEAR
GLOBAL PASCAL PUW:NEAR
GLOBAL PASCAL PUD:NEAR
GLOBAL PASCAL PSB:NEAR
GLOBAL PASCAL PSW:NEAR
GLOBAL PASCAL PSD:NEAR
GLOBAL PASCAL PFST:NEAR
GLOBAL PASCAL GETCH:NEAR
GLOBAL PASCAL EDITSTR:NEAR
GLOBAL PASCAL SETCSRPOS:NEAR
GLOBAL PASCAL GETCSRPOS:NEAR
GLOBAL PASCAL UPDATECSR:NEAR
GLOBAL PASCAL SETCSRTYPE:NEAR
GLOBAL PASCAL SETCSR:NEAR
GLOBAL PASCAL GETCSR:NEAR
GLOBAL PASCAL BEEP:NEAR
ENDIF